package com.archgeek.java.lru;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 *
 * 设计一个LRU (Least Recently Used) 缓存，实现两个操作：
 * 1. 获取数据：如果数据在缓存中存在，则返回数据；如果数据不在缓存中，则从数据源中获取数据，并将数据添加到缓存中。
 * 2. 更新数据：如果数据在缓存中已经存在，则将数据移动到缓存的队列头部；如果数据不在缓存中，则添加数据到缓存中，
 *      如果缓存已满，则移除最近最少使用的数据，并将新数据添加到缓存的队列头部。
 * 要求：
 * 1. 缓存具有固定大小，当缓存中的数据达到最大容量时，需要进行LRU淘汰策略。
 * 2. 设计数据结构来存储缓存数据，并实现获取数据和更新数据的方法。
 *
 * @author pizhihui
 * @date 2024-03-14 14:15
 */
public class LRUDemo {


    Map<Integer, Integer> data;
    LinkedList<Integer> queue;

    // 容量
    int size;
    int maxSize;

    public LRUDemo(int size) {
        maxSize = size;
        data = new HashMap<>(size);
        queue = new LinkedList<>();
    }

    /**
     * 获取数据
     * @param d
     * @return
     */
    public Integer get(int d) {
        Integer res = data.get(d);
        if (null == res) {
            //
            getFromMySQL();
            update(d);
            return d;
        }
        queue.remove(queue.indexOf(d));
        queue.addFirst(d);
        return res;
    }

    /**
     * 更新数据
     * @param d
     */
    public void update(int d) {
        if (size >= maxSize) {
            // 替换数据
//            queue.remove(queue.indexOf(d));
//            data.remove(d);
            Integer del = queue.removeLast();
            data.remove(del);
            System.out.println("要删除的数据:" + del);
        }
        Integer r = data.put(d, d);
        if (r != null) {
            queue.addFirst(d);
        } else {
            queue.addLast(d);
        }
        size++;
    }

    public Integer getFromMySQL() {
        System.out.println("从数据源获取数据.");
        return 76;
    }

    public Integer size() {
        return size;
    }

    public void print() {
        Iterator<Integer> iterator = queue.iterator();
        List<Integer> list = new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        System.out.println("队列值: " + Arrays.toString(list.toArray()));
    }


    public static void main(String[] args) {

        LRUDemo lruDemo = new LRUDemo(2);
//        Integer it = lruDemo.get(2);
//        System.out.println(it);

//        Integer it2 = lruDemo.get(2);
//        System.out.println(it2);

        lruDemo.update(1);
        lruDemo.print();
        lruDemo.update(2);
        lruDemo.print();
        lruDemo.update(3);
        lruDemo.print();
        lruDemo.update(4);
        lruDemo.print();
        lruDemo.update(5);
        lruDemo.print();
        lruDemo.update(6);
        lruDemo.print();
        lruDemo.update(7);
        lruDemo.print();
        lruDemo.update(8);
        lruDemo.print();
        lruDemo.update(9);
        lruDemo.print();
        lruDemo.update(10);
        lruDemo.print();
    }


}
